/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.netcracker.action;

import com.netcracker.DAO.Characteristic;
import com.netcracker.DAO.CharacteristicDAO;
import com.netcracker.DAO.ComponentDAO;
import com.netcracker.DAO.ComponentGroupDAO;
import com.netcracker.DAO.ConstClass;
import com.netcracker.DAO.OrderBeforeProcessing;
import com.netcracker.DAO.Template;
import com.netcracker.DAO.TemplateDAO;
import com.netcracker.applications.om.opf.OrderComponentValue;
import com.netcracker.applications.om.opf.OrderManagerConst;
import com.netcracker.applications.opf.pom.POMOperations;
import com.netcracker.applications.opf.pom.ProductOrderValue;
import com.netcracker.applications.opf.pom.inmemory.ProductOrderManager;
//import com.netcracker.applications.spfpp.common.core.AbstractPersistenceAction;
import com.netcracker.applications.spfpp.common.core.NCDataObjectManager;
//import com.netcracker.applications.spfpp.common.core.PersistenceUtils;
import com.netcracker.applications.spfpp.common.core.impl.NCDataObjectManagerImpl;
import com.netcracker.applications.spfpp.opf.flowcomposer.FlowComposer;
import com.netcracker.ejb.attribute.Attribute;
import com.netcracker.ejb.attribute.AttributeHome;
import com.netcracker.ejb.framework.DateTimeFormatHelper;
import com.netcracker.ejb.framework.HomeInterfaceHelper;
import com.netcracker.platform.core.ncdo.model.dataobject.MutableNCDataObject;
import com.netcracker.platform.core.ncdo.persistence.PersistenceConfiguration;
import com.netcracker.platform.core.ncdo.persistence.PersistenceConfigurationManager;
import com.netcracker.platform.core.ncdo.persistence.PersistenceContext;
import com.netcracker.platform.orchestrator.core.model.OrchestrationConstants;
import com.netcracker.platform.orchestrator.core.orm.SafeLifecycleManager;
import com.netcracker.platform.orchestrator.ui.mediation.lifecyclemanagement.ExecutionManager;
import com.netcracker.platform.toolset.TxHelperTool;
//import com.netcracker.web.FrontCommand;
import java.io.IOException;
import java.math.BigInteger;
import java.rmi.RemoteException;
import java.text.ParseException;
import java.util.ArrayList;
//import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.FinderException;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author user
 */
public class OrderAction {

    public static final BigInteger INT_ORD_TYPE_ID = new BigInteger("9135983487413772981");
    public static final BigInteger PHONE_ORD_TYPE_ID = new BigInteger("9135984084413820852");
    public static final BigInteger TV_ORD_TYPE_ID = new BigInteger("9135984084413820847");
    public static final BigInteger ATTR_DOWNSPEED_ID = new BigInteger("9135985467513876340");
    public static final BigInteger ATTR_UPLSPEED_ID = new BigInteger("9135985637413883650");
    public static final BigInteger ATTR_INCLDATA_ID = new BigInteger("9135991507913919798");
    public static final BigInteger ATTR_PRICE_PER_MIN_ID = new BigInteger("9136002209513083922");
    public static final BigInteger ATTR_QUANTCHAN_ID = new BigInteger("9136002209513083915");
    public static final String DOWN_SPEED = "Download Speed";
    public static final String UPL_SPEED = "Upload Speed";
    public static final String INC_DATA = "Included Data";
    final String BASE_PERSISTENCE_CONFIG_ALIAS = "pom.persistence.configuration";
    private ProductOrderManager pom;
    private POMOperations pomOperations = null;
    private PersistenceConfigurationManager confManager = null;
    private PersistenceConfiguration config = null;
    private BigInteger sortingKey = null;
    private String dueDate = null;
    private LinkedList localLinkedList = null;
    ArrayList<Template> listOfInternetProducts;
    ArrayList<Template> listOfTVProducts;
    ArrayList<Template> listOfPhoneProducts;
    List<MutableNCDataObject> newOrders = new ArrayList<MutableNCDataObject>();
    private OrderBeforeProcessing obp;
    private String custId;
    private MutableNCDataObject newOrder;

    public synchronized void orderCreate(final String custId, final OrderBeforeProcessing obp) throws ServletException, IOException, RemoteException {
        this.obp = obp;
        this.custId = custId;
        pom = ProductOrderManager.getInstance();
        confManager = PersistenceConfigurationManager.getInstance();
        config = confManager.getPersistenceConfiguration(BASE_PERSISTENCE_CONFIG_ALIAS);
        pomOperations = new POMOperations();


        final PersistenceContext pc = NCDataObjectManager.createContext(config);
        NCDataObjectManager.bindToThread(pc);

        BigInteger attrID = OrderManagerConst.ESTIMATED_DUE_DATE_ATTR_ID;
        AttributeHome attrHome = (AttributeHome) HomeInterfaceHelper.getInstance().lookupHome("com.netcracker.ejb.attribute.AttributeHome", AttributeHome.class);
        Attribute attr = null;
        try {
            attr = attrHome.findByPrimaryKey(attrID);
        } catch (FinderException ex) {
            Logger.getLogger(com.netcracker.web.OrderproceedCommand.class.getName()).log(Level.SEVERE, null, ex);
        }

        String mask = attr.getMask();
        Date estimatedDueDate = null;
        if (dueDate != null) {
            dueDate = adaptToMask(dueDate, mask);
            try {
                estimatedDueDate = DateTimeFormatHelper.getInstance().parseDate(dueDate, mask);
            } catch (ParseException ex) {
                Logger.getLogger(com.netcracker.web.OrderproceedCommand.class.getName()).log(Level.SEVERE, null, ex);
            }
            sortingKey = new BigInteger(Long.toString(estimatedDueDate.getTime()));
        }



        try {
            final ProductOrderManager productOrderManager = pom;


            try {
                TxHelperTool.executeInSeparateTransaction(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {


                        ProductOrderValue pov;
                        BigInteger newOrderID = null;


                        try {


                            pov = pomOperations.createNewProductOrderValue(obp.getTemplateId(), new BigInteger(custId), sortingKey);
                            newOrder = productOrderManager.createOrder(pov);

                            newOrderID = newOrder.getId();
                            //components
                            for (BigInteger componentTemplateId : obp.getComponentIds()) {
                                OrderComponentValue ocv = pomOperations.createProductOrderComponentValue(componentTemplateId, null, OrderManagerConst.ORDER_COMPONENT_STATUS_CREATED_VALUE);
                                MutableNCDataObject newComponent = pom.addComponent(newOrderID, ocv);

                            }
                            //characteristic
                            BigInteger oTypeId = newOrder.getObjectTypeId();
                            CharacteristicDAO cDAO = new CharacteristicDAO();
                            ArrayList<Characteristic> cList = cDAO.getCaracteristics(obp.getTemplateId());
                            if (oTypeId.equals(INT_ORD_TYPE_ID)) {
                                for (Characteristic characteristic : cList) {
                                    if (characteristic.getName().equals(DOWN_SPEED)) {
                                        newOrder.setValue(ATTR_DOWNSPEED_ID, characteristic.getValue());
                                    } else if (characteristic.getName().equals(UPL_SPEED)) {
                                        newOrder.setValue(ATTR_UPLSPEED_ID, characteristic.getValue());
                                    } else if (characteristic.getName().equals(INC_DATA)) {
                                        newOrder.setValue(ATTR_INCLDATA_ID, characteristic.getValue());
                                    }
                                }

                            } else if (oTypeId.equals(PHONE_ORD_TYPE_ID)) {
                                newOrder.setValue(ATTR_PRICE_PER_MIN_ID, cList.get(0).getValue());
                            } else {
                                newOrder.setValue(ATTR_QUANTCHAN_ID, cList.get(0).getValue());
                            }


                            return null;
                        } catch (RemoteException rm) {

                            System.out.println(rm.getMessage());
                            //   exception = rm.getMessage();
                        } finally {
                        }
                        return null;
                    }
                });


                Thread.sleep(1000);
                TxHelperTool.executeInSeparateTransaction(new Callable<Void>() {
                    public Void call() throws Exception {

                        if (OrderAction.this.newOrders != null) {
                            com.netcracker.ejb.core.security.SecurityFacade.getInstance().getSecuritySys().doAsSystem(
                                    new java.security.PrivilegedExceptionAction<Object>() {
                                public Object run() throws Exception {
                                    MutableNCDataObject parentObj = NCDataObjectManager.findObjectByID(OrchestrationConstants.INSTANCE_PROCESSES_TOPSITE_ID);
                                    com.netcracker.applications.spfpp.opf.flowcomposer.FlowComposer flowComposer = new com.netcracker.applications.spfpp.opf.flowcomposer.FlowComposer();


                                    List<MutableNCDataObject> ordList = null;

                                    ordList = new ArrayList<MutableNCDataObject>();
                                    ordList.add(newOrder);

                                    com.netcracker.platform.orchestrator.core.model.Process process = flowComposer.createExecutionFlow(parentObj, ordList);
                                    SafeLifecycleManager.getInstance().storeProcess(process);
                                    ExecutionManager.process(process.getID(), "execute_process");
                                    pom.startOrder(newOrder.getId());// 
                                    pom.completeOrder(newOrder.getId());// 

                                    return null;
                                }
                            });


                            pc.flush();
                            return null;
                        }
                        return null;
                    }
                });



                Thread.sleep(1000);

            } catch (TxHelperTool.InvocationException invException) {
                invException.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            pc.close();
        }
    }

    protected String adaptToMask(String date, String mask) {
        char[] separator = {'/', ':', '_', ' '};
        char[] dateCh = date.toCharArray();
        char[] maskCh = mask.toCharArray();
        int endPos;
        if (mask.length() >= dateCh.length) {
            endPos = dateCh.length;
        } else {
            endPos = mask.length();
        }
        for (int i = 0; i < endPos; i++) {
            for (int j = 0; j < separator.length; j++) {
                if (dateCh[i] == separator[j] && dateCh[i] != maskCh[i]) {
                    dateCh[i] = maskCh[i];
                }
            }
        }
        date = String.valueOf(dateCh);
        return date;
    }

    public void getTemplates() {
        TemplateDAO templateDAO = new TemplateDAO();
        listOfInternetProducts = templateDAO.getTemplates(ConstClass.INTERNET_CATEGORY_ID);
        listOfTVProducts = templateDAO.getTemplates(ConstClass.TV_CATEGORY_ID);
        listOfPhoneProducts = templateDAO.getTemplates(ConstClass.PHONE_CATEGORY_ID);

        addCharacteristics(listOfInternetProducts);
        addCharacteristics(listOfTVProducts);
        addCharacteristics(listOfPhoneProducts);

        addComponents(listOfTVProducts);
        addComponents(listOfTVProducts);
        addComponents(listOfPhoneProducts);

        addComponentGroups(listOfInternetProducts);
        addComponentGroups(listOfTVProducts);
        addComponentGroups(listOfPhoneProducts);

    }

    private void addCharacteristics(ArrayList<Template> templates) {
        CharacteristicDAO characteristicDAO = new CharacteristicDAO();
        for (Template t : templates) {
            t.setCharacteristic(characteristicDAO.getCaracteristics(t.getId()));
        }
    }

    private void addComponents(ArrayList<Template> templates) {
        ComponentDAO componentDAO = new ComponentDAO();
        for (Template t : templates) {
            t.setComponents(componentDAO.getAllComponents(t.getId()));
        }
    }

    private void addComponentGroups(ArrayList<Template> templates) {
        ComponentGroupDAO componentGroupDAO = new ComponentGroupDAO();
        for (Template t : templates) {
            t.setComponentGroup(componentGroupDAO.getComponentGroups(t.getId()));
        }
    }

    public ArrayList<Template> getListOfInternetProducts() {
        return listOfInternetProducts;
    }

    public ArrayList<Template> getListOfTVProducts() {
        return listOfTVProducts;
    }

    public ArrayList<Template> getListOfPhoneProducts() {
        return listOfPhoneProducts;
    }
}
